package com.colabo.j2ee.web.oaf.security.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.FilterInvocation;

import com.colabo.j2ee.web.core.exception.ServiceException;
import com.colabo.j2ee.web.core.service.impl.DefaultServiceImpl;
import com.colabo.j2ee.web.oaf.menu.IMenuService;
import com.colabo.j2ee.web.oaf.security.AuthUtil;


public class MenuVoter extends DefaultServiceImpl implements AccessDecisionVoter {
	private Log log = LogFactory.getLog(MenuVoter.class);

	public boolean supports(ConfigAttribute attribute) {
		return true;
	}

	public boolean supports(Class clazz) {
		return clazz.isAssignableFrom(FilterInvocation.class);
	}

	public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
		for (ConfigAttribute configAttribute : attributes) {
			String url = configAttribute.getAttribute();
			if (voteMenu(authentication, getMenuList(url))) {
				return ACCESS_GRANTED;
			}
		}
		return ACCESS_ABSTAIN;
	}

	private boolean voteMenu(Authentication authentication, List menuList) {
		for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) {
			for (Iterator it = menuList.iterator(); it.hasNext();) {
				if (grantedAuthority.getAuthority().startsWith(AuthUtil.MENU_PREFIX)
						&& grantedAuthority.getAuthority().endsWith(it.next().toString())) {
					return true;
				}
			}
		}

		return false;
	}

	private List getMenuList(String url) {
		IMenuService menuService = (IMenuService) getBean(IMenuService.BEAN_ID);
		try {
			return menuService.getMenuKyListByUrl(url);
		} catch (ServiceException e) {
			log.error(e);
		}
		return new ArrayList(0);
	}

}
